package com.taokatao.cardmee.business;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.taokatao.cardmee.App;
import com.taokatao.cardmee.C;
import com.taokatao.cardmee.Utils;

import java.util.ArrayList;
import java.util.List;


public class SwipeItemLayout extends FrameLayout {

    private static class Menu {
        String tag;
        String text;
        int backgroundRes;
        OnClickListener clickCallback;
    }

    public interface OnStateChangedListener {
        void onStateChanged(SwipeItemLayout swipeItemLayout, boolean isMenuOpened);

        boolean isLastSwipeClosed();
    }

    private boolean isInterceptTouch;
    private float downX;
    private int touchSlop;

    private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(2);
    private boolean anim;
    private ValueAnimator animator;

    private boolean isMenuOpened;
    private View child;
    private LinearLayout layMenusWrapper;
    private OnStateChangedListener mCallback;
    private OnClickListener onContentClickCallback;

    private final List<Menu> menuList = new ArrayList<>();

    public SwipeItemLayout(Context context) {
        this(context, null);
    }

    public SwipeItemLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    public void setMyOnClickListener(OnClickListener onContentClickListener, OnStateChangedListener callback) {
        onContentClickCallback = onContentClickListener;
        mCallback = callback;
    }

    public void addSupportMenu(String flag, String text, int backgroundRes, OnClickListener clickListener) {
        final Menu menu = new Menu();
        menu.tag = flag;
        menu.text = text;
        menu.backgroundRes = backgroundRes;
        menu.clickCallback = clickListener;
        menuList.add(menu);

        TextView tMenu = makeMenu(getContext());
        tMenu.setText(menu.text);
        tMenu.setTag(menu.tag);
        int spacing = App.i().d1() * 20;
        tMenu.setPadding(spacing, 0, spacing, 0);
        tMenu.setTextSize(18);
        tMenu.setTextColor(0xFFFFFFFF);
        tMenu.setBackgroundResource(menu.backgroundRes);
        Utils.throttleFirstClick(tMenu, new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (menu.clickCallback != null) {
                    menu.clickCallback.onClick(v);
                }
            }
        });
        layMenusWrapper.addView(tMenu);
    }

    public void resetMenu(String[] menus) {
        if (menus != null) {
            layMenusWrapper.setVisibility(View.VISIBLE);

            for (int j = 0; j < layMenusWrapper.getChildCount(); j++) {
                layMenusWrapper.getChildAt(j).setVisibility(View.GONE);
            }

            for (String menu : menus) {
                View menuView = layMenusWrapper.findViewWithTag(menu);
                if (menuView != null) {
                    menuView.setVisibility(View.VISIBLE);
                }
            }
        } else {
            layMenusWrapper.setVisibility(View.GONE);
        }
    }

    public boolean isInAnimation() {
        return anim;
    }

    public boolean isMenuOpened() {
        return isMenuOpened;
    }

    private TextView makeMenu(Context context) {
        TextView tMenu = new TextView(context);
        LinearLayout.LayoutParams lpMenus = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
        lpMenus.gravity = Gravity.RIGHT;
        tMenu.setLayoutParams(lpMenus);
        tMenu.setTextSize(20);
        tMenu.setGravity(Gravity.CENTER);
        int dip1 = (int) (1 * getResources().getDisplayMetrics().density + 0.5f);
        tMenu.setPadding(dip1 * 15, 0, dip1 * 15, 0);
        return tMenu;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = ev.getRawX();
                isInterceptTouch = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if (!isMenuOpened) {
                    if (!isInterceptTouch && downX - ev.getRawX() > touchSlop) {
                        isInterceptTouch = true;
                    }
                } else {
                    if (Math.abs(downX - ev.getRawX()) > touchSlop) {
                        isInterceptTouch = true;
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                break;
        }
        getParent().requestDisallowInterceptTouchEvent(isInterceptTouch);
        return isInterceptTouch ? true : super.onInterceptTouchEvent(ev);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        child = getChildAt(0);
        child.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!anim) {
                    if (isMenuOpened) {
                        animRestore(isMenuOpened = false);
                    } else {
                        if (onContentClickCallback != null) {
                            onContentClickCallback.onClick(v);
                        }
                    }
                }
            }
        });

        layMenusWrapper = new LinearLayout(getContext());
        LayoutParams lpMenus = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        lpMenus.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
        addView(layMenusWrapper, 0, lpMenus);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!anim) {
            if (mCallback != null) {
                if (!mCallback.isLastSwipeClosed()) {
                    return super.onTouchEvent(event);
                }
            }

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    return true;
                case MotionEvent.ACTION_MOVE:
                    float offsetMoveX = event.getRawX() - downX;
                    offsetMoveX += isMenuOpened ? -layMenusWrapper.getWidth() : 0;
                    if (offsetMoveX > 0) {
                        offsetMoveX = 0;
                    } else if (offsetMoveX < -layMenusWrapper.getWidth()) {
                        offsetMoveX = -layMenusWrapper.getWidth();
                    }
                    child.setTranslationX(offsetMoveX);
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    float offsetUpX = event.getRawX() - downX;
                    int menusDividerLine = layMenusWrapper.getWidth() / 4;
                    animRestore(-offsetUpX > menusDividerLine);
                    break;
            }
        }
        return super.onTouchEvent(event);
    }


    public void animRestore(boolean on) {
        if (animator != null) animator.cancel();

        isMenuOpened = on;
        final float childTranslationX = child.getTranslationX();
        final float targetResultX = on ? -layMenusWrapper.getWidth() : 0;

        animator = ValueAnimator.ofFloat(1, 0);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float currValue = (float) animation.getAnimatedValue();
                child.setTranslationX(targetResultX - (targetResultX - childTranslationX) * currValue);
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                child.setTranslationX(targetResultX);
                anim = false;
                if (mCallback != null) {
                    mCallback.onStateChanged(SwipeItemLayout.this, isMenuOpened);
                }
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                anim = true;
            }
        });
        animator.setDuration(C.settings.ANIMATION_TIME);
        animator.setInterpolator(decelerateInterpolator);
        animator.start();
    }
}
